package com.latam.arq.example.web.admin.managedbeans;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AbortProcessingException;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.latam.arq.commons.appconfig.properties.AppConfigException;
import com.latam.arq.commons.appconfig.properties.AppConfigUtil;
import com.latam.arq.example.admin.logger.JMSLoggerUtil;

/**
 * ExampleLogViewerMB
 * Example ManagedBean for use the realtime log view and downloading log file capabilities. 
 * (According to the project requirements, this class must be removed or moved to the project package.)
 * 
 * @author LATAM Enterprise Architect
 * @author francisco.mendez@lan.com (Francisco Mendez)
 * @author cesar.pasache@lan.com (Cesar Pasache) 
 * 
 */
@ManagedBean(name = "exampleLogViewer")
@ViewScoped
public class ExampleLogViewerMB{
	private static final Logger logger = LoggerFactory
			.getLogger(ExampleLogViewerMB.class);

	private static final long MAX_FILE_LENGTH = 10L * 1024L * 1024L; //10 MB 
	
	private static String DEFAULT_LOG4J_PROPERTY_FILE 	= "log4j.properties";
	private static String DEFAULT_LOG_FILE_PROPERTY_KEY = "log4j.appender.LogToFile.File";
	private static String DEFAULT_LOG_FOLDER 			= "logweblogic/";

	private String appName = AppConfigUtil.getAppName();
	private File logFolder = null;
	
	@PostConstruct
	void init(){
		try {
			final Properties p = new Properties();
			p.load(AppConfigUtil.getResourceFromAppFolder(DEFAULT_LOG4J_PROPERTY_FILE));

			final String logFileName = p.getProperty(DEFAULT_LOG_FILE_PROPERTY_KEY);
			final File logFile = new File( logFileName );

			logFolder = logFile.getParentFile();
			if (logger.isDebugEnabled()){
				logger.debug("Detected Log Folder: " + logFolder);
			}
			
			return;
			
		} catch (final IOException e) {
			if (logger.isWarnEnabled()){
				logger.warn("Couldn't get log folder from properties, using default (" + DEFAULT_LOG_FOLDER + ").",e);
			}
		} catch (final AppConfigException e) {
			if (logger.isWarnEnabled()){
				logger.warn("Couldn't get log folder from properties, using default (" + DEFAULT_LOG_FOLDER + ").",e);
			}
		}

		logFolder = new File(DEFAULT_LOG_FOLDER);
	};


	/**
	 * Lists the log files in the log folder
	 * 
	 * @return
	 */
	public List<File> getLogFileList() {
		final ArrayList<File> files = new ArrayList<File>();
		for (final File f : logFolder.listFiles()) {
			if ((f.isFile()) && (f.getName().startsWith(appName)) && (f.getName().toLowerCase().endsWith(".log"))){
				files.add(f);
			}
		}
		return files;
	}

	/**
	 * (action) Return the ziped log file
	 * @param fileName
	 * @return
	 */
	public StreamedContent getFile( final String fileName ) {
		try {
			final byte[] zipFile = zipFile(fileName); 
			final ByteArrayInputStream bais = new ByteArrayInputStream( zipFile );
			return new DefaultStreamedContent( bais , 
					"application/zip", fileName
					+ ".zip");
		} catch (final IOException e) {
			if (logger.isErrorEnabled()){
				logger.error("Error compressing to zip file " + fileName, e);
			}
		}
		return null;
	}
	
	/**
	 * Zip a file in log folder and returns the path of the compressed file
	 * 
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	private byte[] zipFile( final String fileName ) throws IOException, AbortProcessingException {
		final ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		final File file = new File(logFolder, fileName);
		
		logger.info("MAX_FILE_LENGTH: " + MAX_FILE_LENGTH);
		logger.info("Log filelenght: " + file.length());
		
		if (file.length() > MAX_FILE_LENGTH){
			throw new AbortProcessingException("The log file exceed the maximum file length.");
		}
		
		final ZipOutputStream zos = new ZipOutputStream(baos);
		final FileInputStream fis = new FileInputStream(file);
		
		zos.putNextEntry(new ZipEntry(file.getName()));
		byte buffer[] = new byte[2048];
		int i;
		while ((i = fis.read(buffer)) > 0) {
			zos.write(buffer, 0, i);
		}

		fis.close();		
		zos.closeEntry();
		zos.close();
		baos.close();

		return baos.toByteArray();
	}
	
	public long getMaxFileLength() {
		return MAX_FILE_LENGTH;
	}

	/**
	 * (action) Enable the JMS Logger 
	 */
	public void enableJmsLogger(){
		JMSLoggerUtil.enableJmsLogger();
	}

	/**
	 * (action) Disable the JMS Logger 
	 */
	public void disableJmsLogger(){
		JMSLoggerUtil.disableJmsLogger();
	}
	
	/**
	 * (action) Disable the JMS Logger 
	 */
	public boolean isJmsLoggerEnabled(){
		return JMSLoggerUtil.isJmsLoggerEnabled();
	}	
	
	public void testLogger(){
		int numOfMessages = (int)(Math.random()*30.0)+1;
		for(int idx=1;idx<=numOfMessages;idx++){
			logger.info("Test line " + idx + ".");
		}
	}
}
